Automate the creation of requirement.txt and fetch deps - #2118
Conversation
By running this script, we will able to create and update the requirements.txt by providing the input directory like thirdparty . Also adding deps setuptools which is deps of zc.lockfile-2.0 Signed-off-by: Abhishek Kumar <abhishek.kasyap09@gmail.com>
Identify Python version to extract abi of wheels which helps us in filtering the required deps. Signed-off-by: Abhishek Kumar <abhishek.kasyap09@gmail.com>
This script will fetch dependencies with all corresponding files(.whl,.tar.gz,.LICENCE,.NOTICE,.ABOUT) from the given target . This feature will ask ScanCode's developer to provide dependencies as package_name,version and target directory where the built wheels and tarballs would be fetched. Signed-off-by: Abhishek Kumar <abhishek.kasyap09@gmail.com>
pombredanne
left a comment
There was a problem hiding this comment.
Thanks... see my comments!
| ) | ||
| ] | ||
| if not (os.path.isdir("required_deps")): | ||
| os.mkdir("required_deps") |
There was a problem hiding this comment.
Why do you create that directory?
There was a problem hiding this comment.
To filter the dependencies of specific python version we want because we have both py2 and py3 wheels in thirdparty. Don't worry it will deleted later by scripts itself.
There was a problem hiding this comment.
OK, so please add a comment explaining that... and also this may not be created where you want. Make sure you use a well known location or better use some temp directory instead since this is temporary
There was a problem hiding this comment.
Please use a temp dir instead
| @@ -0,0 +1,128 @@ | |||
| # -*- coding: utf-8 -*- | |||
There was a problem hiding this comment.
Please do not name this scancode ;) that's confusing!
There was a problem hiding this comment.
Suggest the better name.
| about = [files for files in dependency if files.endswith(".ABOUT")] | ||
| notice = [files for files in dependency if files.endswith(".NOTICE")] | ||
| license = [files for files in dependency if files.endswith(".LICENSE")] | ||
| print(*whl, sep="\n") |
There was a problem hiding this comment.
why do you print all that ?
There was a problem hiding this comment.
Because scancode's developer want to fetch the deps in target directory. Script will know developer by printing the info of deps.
There was a problem hiding this comment.
that's too verbose by default. Hide the prints behind an option
There was a problem hiding this comment.
it shows ONLY .ABOUT/.NOTICE/.LICENCE/.whl/.tar.gz . Not too verbose i have seen
| @@ -0,0 +1,15 @@ | |||
| about_resource: setuptools-41.2.0-py2.py3-none-any.whl | |||
There was a problem hiding this comment.
We should already have setuptools..... good catch. But please do not commit it there, craft another PR instead just for that.
There was a problem hiding this comment.
Don't worry, i already mentioned in PR description. FYI there is no deps named setuptools . That's why i added wheels setuptools also here.
There was a problem hiding this comment.
I get that, but please provide a different PR for adding that back (and FYI zopefoundation/zc.lockfile#22 )
pombredanne
left a comment
There was a problem hiding this comment.
Thanks... please see my comments inline
| "--output-file", | ||
| output_file, | ||
| "--verbose", | ||
| "--upgrade-package", |
There was a problem hiding this comment.
why do you do this? we never want to do some unwanted upgrade-package IMHO and what is "package_name", below about?
There was a problem hiding this comment.
this feature alow you to upgrade specfic package. See help by running this arg.
There was a problem hiding this comment.
I known that but what is "package_name" I know of no package whose name is "package_name"
If this is some kind of magic, explain it in comments, do not make me chase down the help of that command
There was a problem hiding this comment.
In any case why would I want to upgrade a package there? Please elaborate and explain in comments
There was a problem hiding this comment.
Package name may be intbitset, banal, urlpy . Anything deps that exist in thirdparty
|
|
||
| parser.add_argument( | ||
| "--upgrade", | ||
| help="Upgrade all dependencies to new version. ", |
There was a problem hiding this comment.
nit: you have trailing whitespaces here and elsewhere
| """ | ||
| Generate a requirement.txt file of all dependencies present in thirdparty. | ||
| """ | ||
| thirdparty = list(resource_iter(input_dir, with_dirs=False)) |
There was a problem hiding this comment.
The list() wrapper is not needed here
|
|
||
| def generate_req_text(input_dir, output_file=False, package_name=False): | ||
| """ | ||
| Generate a requirement.txt file of all dependencies present in thirdparty. |
There was a problem hiding this comment.
and what are the args?
this should IMHO be something such as:
Generate a requirement file at `output_file` of all dependencies wheels and sdists present in the `input_dir` directory.
If a `package_name` is provided it will be updated to its latest version.
though I am not sure this is true for package_name
Also output_file=False, package_name=False is weird. These should be None... and output_file should always be required
Also what is the base used there? the setup.py or some requirements.in file? I think we will need a requirements.in file
There was a problem hiding this comment.
Base used here : setup.py and no need of requirements.in file. And by default output_file is requirements.txt and it is default arguments.
| about = [files for files in dependency if files.endswith(".ABOUT")] | ||
| notice = [files for files in dependency if files.endswith(".NOTICE")] | ||
| license = [files for files in dependency if files.endswith(".LICENSE")] | ||
| print(*whl, sep="\n") |
There was a problem hiding this comment.
that's too verbose by default. Hide the prints behind an option
| @@ -0,0 +1,15 @@ | |||
| about_resource: setuptools-41.2.0-py2.py3-none-any.whl | |||
There was a problem hiding this comment.
I get that, but please provide a different PR for adding that back (and FYI zopefoundation/zc.lockfile#22 )
Signed-off-by: Abhishek Kumar <abhishek.kasyap09@gmail.com>
Signed-off-by: Abhishek Kumar <abhishek.kasyap09@gmail.com>
pombredanne
left a comment
There was a problem hiding this comment.
Thanks... see my comments
|
|
||
| def main_with_args(args: str) -> None: | ||
| parser = argparse.ArgumentParser( | ||
| description="""Fetch a specific package with version in given target like thirdparty by default. |
There was a problem hiding this comment.
Thsi command seems if fetches nothing at all, does it?
There was a problem hiding this comment.
it description of function , you know this thing by running --help option. I help developer when he put --help option
There was a problem hiding this comment.
It should be instead:
Search PACKAGE_NAME (with an optional VERSION_OF_PACKAGE) in the TARGET_DIR directory.
Print results on screen.
|
|
||
| def generate_req_text(input_dir, output_file=None, package_name=None): | ||
| """ | ||
| Generate a requirement file at `output_file`(by default requirements.txt) of all dependencies wheels and sdists present in the `input_dir` directory. |
There was a problem hiding this comment.
Please wrap this. Also if you want a default of (by default requirements.txt)... then set the default in the function definition and not as None
There was a problem hiding this comment.
Already set as defaults.
There was a problem hiding this comment.
By wrap, wrap the very long lines.
| ) | ||
| ] | ||
| if not (os.path.isdir("required_deps")): | ||
| os.mkdir("required_deps") |
There was a problem hiding this comment.
Please use a temp dir instead
| "--output-file", | ||
| output_file, | ||
| "--verbose", | ||
| "--upgrade-package", |
There was a problem hiding this comment.
I known that but what is "package_name" I know of no package whose name is "package_name"
If this is some kind of magic, explain it in comments, do not make me chase down the help of that command
| "--output-file", | ||
| output_file, | ||
| "--verbose", | ||
| "--upgrade-package", |
There was a problem hiding this comment.
In any case why would I want to upgrade a package there? Please elaborate and explain in comments
| "--no-index", | ||
| ] | ||
| ) | ||
| shutil.rmtree("required_deps") |
There was a problem hiding this comment.
I would rather you use a temp file with a "with" context manager to avoid leaving dangling files
There was a problem hiding this comment.
It is not a file , it is directory
|
|
||
| parser.add_argument( | ||
| "--output", | ||
| help="Output file name. Required if more than one input file is given. Will be derived from input file otherwise.", |
There was a problem hiding this comment.
Avoid implicit, derived name. It is preferred to always require an input instead
There was a problem hiding this comment.
pip-tools uses --output-file for same purpose why should i not not use --output?
There was a problem hiding this comment.
My point is to avoid using a derived name. Instead make this always required and not implied.
There was a problem hiding this comment.
Ok , your call i changing the option --output to --requirement . And making always required.
| tpdir = args.deps_directory | ||
| output_file = args.output | ||
| package_name = args.upgrade_package | ||
| upgrade = args.upgrade or None |
There was a problem hiding this comment.
This argument is not used at all... so what is it for?
There was a problem hiding this comment.
upgrade is for upgrading all packages whereas upgrade_package is for specific package,
There was a problem hiding this comment.
Is not an argument used anywhere in your functions
There was a problem hiding this comment.
Great catch .It is an option just like ON/OFF . It is used here only , i have tested it it works, if you want i will paste output here.
Signed-off-by: Abhishek Kumar <abhishek.kasyap09@gmail.com>
c351eed to
0a9db9f
Compare
Signed-off-by: Abhishek Kumar <abhishek.kasyap09@gmail.com>
| "--verbose", | ||
| "--allow-unsafe", | ||
| "--upgrade-package", | ||
| "package_name", |
There was a problem hiding this comment.
"package_name" is NOT a variable here ... but a plain string. This cannot work as it is... you need to test your code.
There was a problem hiding this comment.
Oh, yeah it is function parameter through arguments . I have treated like temp dir as That is also also in double quotes but it is dir not variable . Same issue with upgrade parameter also.
Signed-off-by: Abhishek Kumar <abhishek.kasyap09@gmail.com>
Signed-off-by: Abhishek Kumar <abhishek.kasyap09@gmail.com>
| parser = argparse.ArgumentParser( | ||
| description="""Fetch a specific package with version in given target like thirdparty by default. | ||
| EXAMPLE: | ||
| scancode.py \\ |
pombredanne
left a comment
There was a problem hiding this comment.
See my nitpickings inline for your review!
Thanks you for your persistence!
| import sys | ||
|
|
||
|
|
||
| def search_package(package_name, target, version): |
There was a problem hiding this comment.
Please version=None since this is optional
| import argparse | ||
| import fnmatch | ||
| from commoncode.fileutils import resource_iter | ||
| import sys |
|
|
||
| def search_package(package_name, target, version): | ||
| """ | ||
| Search specific package in given directory with all corresponding files. |
There was a problem hiding this comment.
Use instead:
Search `package_name` (with an optional `version`) in the `target` directory. Print results on screen.
|
|
||
| def main_with_args(args: str) -> None: | ||
| parser = argparse.ArgumentParser( | ||
| description="""Fetch a specific package with version in given target like thirdparty by default. |
There was a problem hiding this comment.
It should be instead:
Search PACKAGE_NAME (with an optional VERSION_OF_PACKAGE) in the TARGET_DIR directory.
Print results on screen.
|
|
||
| parser.add_argument( | ||
| "--target", | ||
| help=" a target directory where the built wheels and tarballs would be fetched.", |
There was a problem hiding this comment.
Use this:
"Directory to search for package wheels and tarballs. [default: thirdparty]"
|
|
||
| def generate_req_text(input_dir, output_file=None, package_name=None): | ||
| """ | ||
| Generate a requirement file at `output_file`(by default requirements.txt) of all dependencies wheels and sdists present in the `input_dir` directory. |
There was a problem hiding this comment.
By wrap, wrap the very long lines.
| 'pip-compile', | ||
| '--generate-hashes', | ||
| '--find-links', | ||
| 'temp dir', |
There was a problem hiding this comment.
I mean to use this https://docs.python.org/3/library/tempfile.html?highlight=tempfile#module-tempfile
No a dir name temp dir
| if package_name: | ||
| pip_args.extend(['--upgrade-package', package_name]) | ||
| run(pip_args) | ||
| rmtree('temp dir') |
There was a problem hiding this comment.
With a proper https://docs.python.org/3/library/tempfile.html?highlight=tempfile#module-tempfile you will NOT need to rm anything, with will be handled for you if you use a context manager.
such as this example from the Python doc:
# create a temporary directory using the context manager
>>> with tempfile.TemporaryDirectory() as tmpdirname:
... print('created temporary directory', tmpdirname)
.... do your things here
| --deps_directory DEPS_DIRECTORY \\ | ||
| --output OUTPUT \\ | ||
| --upgrade_package PACKAGE_NAME \\ | ||
| """, |
There was a problem hiding this comment.
Please remove this example.
| package_name = args.upgrade_package | ||
| upgrade = args.upgrade or False | ||
| generate_req_text(tpdir, requirement_file, package_name, upgrade) | ||
|
|
There was a problem hiding this comment.
prefer named keyword arguments for example:
(tpdir=tpdir, requirement_file=requirement_file, package_name=package_name, upgrade=upgrade) But do not use these names... use the same variable names on both sides: e.g. if you use args.deps_directory then usedeps_directoryand nottpdir`
…requirements.txt
Signed-off-by: Abhishek Kumar <abhishek.kasyap09@gmail.com>
| from fnmatch import fnmatchcase | ||
| import os | ||
| from subprocess import run | ||
| from shutil import copy, rmtree |
There was a problem hiding this comment.
nitpicking: your imports are not sorted. Try to use https://pypi.org/project/isort/
There was a problem hiding this comment.
Oh , i missed that .Also i have to remove unused import
| def generate_req_text(find_links, req_file, package_name=None, upgrade=False): | ||
| """ | ||
| Generate a requirement file at `req_file` of all dependencies wheels and | ||
| sdists present in the `input_dir` directory.If a `package_name` is provided |
There was a problem hiding this comment.
There is no input_dir?
...sdists present in the input_dir directory...
Do you mind doing an extra review pass on this PR and #2117 to make sure the docstrings are well synced with the actual function arguments and what the function does>
There was a problem hiding this comment.
I think, this PR has reviewed many times. I would like work on diff PR
Signed-off-by: Abhishek Kumar <abhishek.kasyap09@gmail.com>
Signed-off-by: Philippe Ombredanne <pombredanne@nexb.com>
pombredanne
left a comment
There was a problem hiding this comment.
This is looking fine. Thank you! merging
By running this script, we will able to create and update the requirements.txt by providing the input directory like thirdparty .
This script will fetch dependencies with all corresponding files(.whl,.tar.gz,.LICENCE,.NOTICE,.ABOUT) from the given target . This feature will ask ScanCode's developer to provide dependencies as package_name,version and target directory where the built wheels and tarballs would be fetched.
Signed-off-by: Abhishek Kumar abhishek.kasyap09@gmail.com
Fixes aboutcode-org/skeleton#50 #2087